home *** CD-ROM | disk | FTP | other *** search
/ CU Amiga Super CD-ROM 17 / CU Amiga Magazine's Super CD-ROM 17 (1997)(EMAP Images)(GB)[!][issue 1997-12].iso / CUCD / Programming / DiceSource / src / dc1 / asubs.c < prev    next >
C/C++ Source or Header  |  1997-09-09  |  16KB  |  801 lines

  1. /*
  2.  *    (c)Copyright 1992-1997 Obvious Implementations Corp.  Redistribution and
  3.  *    use is allowed under the terms of the DICE-LICENSE FILE,
  4.  *    DICE-LICENSE.TXT.
  5.  */
  6.  
  7. /*
  8.  *  ASUBS.C
  9.  *
  10.  */
  11.  
  12. /*
  13. **      $Filename: asubs.c $
  14. **      $Author: dice $
  15. **      $Revision: 30.326 $
  16. **      $Date: 1995/12/24 06:09:36 $
  17. **      $Log: asubs.c,v $
  18.  * Revision 30.326  1995/12/24  06:09:36  dice
  19.  * .
  20.  *
  21.  * Revision 30.5  1994/06/13  18:37:23  dice
  22.  * byte ordering portability
  23.  *
  24.  * Revision 30.0  1994/06/10  18:04:46  dice
  25.  * .
  26.  *
  27.  * Revision 1.3  1993/11/22  00:28:36  jtoebes
  28.  * Final cleanup to eliminate all cerror() messages with strings.
  29.  *
  30.  * Revision 1.2  1993/09/06  13:17:17  jtoebes
  31.  * Fixed BUG01091 - Bad error for undefined structure tag.
  32.  * Eliminated message because it is now caught in the front end parsing
  33.  * routines for structures/unions/arrays.
  34.  *
  35. **/
  36.  
  37. #include "defs.h"
  38. #include "asm.h"
  39.  
  40. Prototype char SizC[];
  41. Prototype char StorBuf[2][1024];
  42.  
  43. char SizC[] = { '0', 'b', 'w', '0', 'l', '?' };
  44. char StorBuf[2][1024];
  45.  
  46. Prototype char *RegMaskToString(long, short *);
  47. Prototype char *StorToString(Stor *, short *);
  48. Prototype char *StorToStringBuf(Stor *, char *);
  49. Prototype long SameStorage(Stor *, Stor *);
  50. Prototype long SameRegister(Stor *, Stor *);
  51. Prototype long RegisterMaskConflict(Stor *, ulong);
  52. Prototype long ImmStorage(Stor *);
  53. Prototype void outop(char *, short, Stor *, Stor *);
  54. Prototype void GenStaticData(Var *);
  55. Prototype void GenDataElm(Exp *, Type *);
  56. Prototype char *itohex(char *, ulong);
  57. Prototype char *itodec(char *, ulong);
  58.  
  59. Prototype void AutoAggregateBeg(Stor *, Type *);
  60. Prototype void AutoAggregate(void *, long);
  61. Prototype void AutoAggregateEnd(void);
  62. Prototype void AutoAggregateSync(void);
  63.  
  64. char *
  65. RegMaskToString(mask, pcnt)
  66. long mask;
  67. short *pcnt;
  68. {
  69.     static char buf[128];
  70.     short i;
  71.     short c = 0;
  72.     char *ptr = buf;
  73.  
  74.     for (i = 0; i < 32; ++i) {
  75.     if (mask & (1 << i)) {
  76.         if (c++)
  77.         *ptr++ = '/';
  78.         if (i < RB_ADDR) {
  79.         *ptr++ = 'D';
  80.         *ptr++ = i + '0';
  81.         } else {
  82.         *ptr++ = 'A';
  83.         *ptr++ = i + ('0' - RB_ADDR);
  84.         }
  85.     }
  86.     }
  87.     *pcnt = c;
  88.     *ptr = 0;
  89.     return(buf);
  90. }
  91.  
  92. char *
  93. StorToString(s, plen)
  94. Stor *s;
  95. short *plen;
  96. {
  97.     static char *Ptr = StorBuf[0];
  98.     char *res;
  99.  
  100.     Ptr = ((Ptr == StorBuf[0]) ? StorBuf[1] : StorBuf[0]);
  101.     res = StorToStringBuf(s, Ptr);
  102.     if (plen)
  103.     *plen = res - Ptr;
  104.     return(Ptr);
  105. }
  106.  
  107. char *
  108. StorToStringBuf(s, base)
  109. Stor *s;
  110. char *base;
  111. {
  112.     char *t = base;
  113.  
  114.     switch(s->st_Type) {
  115.     case ST_PtrConst:
  116.     *t = '$';
  117.     t = itohex(t + 1, s->st_PtrConst);
  118.     if ((long)s->st_PtrConst >= -32768 && (long)s->st_PtrConst < 32768) {
  119.         *t = '.'; ++t;
  120.         *t = 'W'; ++t;
  121.     }
  122.     break;
  123.     case ST_IntConst:        /*  complication is for pretty output */
  124.     *t = '#'; ++t;
  125.     if (s->st_IntConst < 0) {
  126.         *t = '-'; ++t;
  127.         *t = '$'; ++t;
  128.         t = itohex(t, -s->st_IntConst);
  129.     } else {
  130.         *t = '$'; ++t;
  131.         t = itohex(t, s->st_IntConst);
  132.     }
  133.     break;
  134.     case ST_FltConst:
  135.     t += sprintf(t, "<flt-const>");
  136.     break;
  137.     case ST_StrConst:
  138.     dbprintf(("asm-gen, string constant not turned into label"));
  139.     Assert(0);
  140.     t += sprintf(t, "<str-const>");
  141.     break;
  142.     case ST_Reg:
  143.     if (s->st_RegNo < RB_ADDR) {
  144.         *t = 'D'; ++t;
  145.         if (s->st_RegNo < 10) {
  146.         *t = s->st_RegNo + '0';
  147.         ++t;
  148.         } else {
  149.         t[0] = '1';
  150.         t[1] = s->st_RegNo + ('0' - 10);
  151.         t += 2;
  152.         }
  153.     } else {
  154.         *t = 'A'; ++t;
  155.         if (s->st_RegNo < RB_ADDR + 10) {
  156.         *t = s->st_RegNo + ('0' - RB_ADDR);
  157.         ++t;
  158.         } else {
  159.         t[0] = '1';
  160.         t[1] = s->st_RegNo + ('0' - 10 - RB_ADDR);
  161.         t += 2;
  162.         }
  163.     }
  164.     break;
  165.     case ST_RelArg:
  166.     {
  167.         long offset = s->st_Offset;
  168.  
  169.         *t = 'l'; ++t;
  170.         t = itodec(t, LabelRegsUsed);
  171.  
  172.         /*
  173.          *    If procedure returns a structure take into account arguments
  174.          */
  175.  
  176.         switch(ProcVar->Type->SubType->Id) {
  177.         case TID_STRUCT:
  178.         case TID_UNION:
  179.         offset += 4;
  180.         break;
  181.         }
  182.  
  183.         if (s->st_RegNo == RB_SP)
  184.         offset -= 4;
  185.  
  186.         if (offset >= 0) {
  187.         *t = '+';
  188.         ++t;
  189.         }
  190.         t = itodec(t, offset);
  191.  
  192.         *t = '('; ++t;
  193.         *t = 'A'; ++t;
  194.         if (s->st_RegNo < RB_ADDR + 10) {
  195.         *t = s->st_RegNo + ('0' - RB_ADDR);
  196.         ++t;
  197.         } else {
  198.         t[0] = '1';
  199.         t[1] = s->st_RegNo + ('0' - RB_ADDR - 10);
  200.         t += 2;
  201.         }
  202.         *t = ')'; ++t;
  203.     }
  204.     break;
  205.     case ST_RelReg:
  206.     if (s->st_RegNo < RB_ADDR)
  207.     {
  208.         dbprintf(("asubs: rel(Dn) request! ??"));
  209.         Assert(0);
  210.     }
  211.     if (s->st_Offset)
  212.         t = itodec(t, s->st_Offset);
  213.     *t = '('; ++t;
  214.     *t = 'A'; ++t;
  215.     if (s->st_RegNo < RB_ADDR + 10) {
  216.         *t = s->st_RegNo + ('0' - RB_ADDR);
  217.         ++t;
  218.     } else {
  219.         t[0] = '1';
  220.         t[1] = s->st_RegNo + ('0' - RB_ADDR - 10);
  221.         t += 2;
  222.     }
  223.     *t = ')'; ++t;
  224.     break;
  225.     case ST_RegIndex:    /*  offset(An,Dn.[W/L])     */
  226.     if (s->st_Offset) {
  227.         t = itodec(t, s->st_Offset);
  228.     } else {
  229.         *t = '0';
  230.         ++t;
  231.     }
  232.     *t = '('; ++t;
  233.     *t = 'A'; ++t;
  234.     if (s->st_RegNo < RB_ADDR + 10) {
  235.         *t = s->st_RegNo + ('0' - RB_ADDR);
  236.         ++t;
  237.     } else {
  238.         t[0] = '1';
  239.         t[1] = s->st_RegNo + ('0' - RB_ADDR - 10);
  240.         t += 2;
  241.     }
  242.  
  243.     *t = ','; ++t;
  244.     if (s->st_RegNo2 >= RB_ADDR) {
  245.         t[0] = 'A';
  246.         t[1] = s->st_RegNo2 + ('0' - RB_ADDR);
  247.     } else {
  248.         t[0] = 'D';
  249.         t[1] = s->st_RegNo2 + '0';
  250.     }
  251.     t += 2;
  252.  
  253.     *t = '.'; ++t;
  254.     if (s->st_Flags & SF_IDXWORD)
  255.         *t = 'W';
  256.     else
  257.         *t = 'L';
  258.     ++t;
  259.  
  260.     if (s->st_Flags & (SF_IDXSCAL2|SF_IDXSCAL4|SF_IDXSCAL8)) {
  261.         *t = '*'; ++t;
  262.         if (s->st_Flags & SF_IDXSCAL2)
  263.         *t = '2';
  264.         else if (s->st_Flags & SF_IDXSCAL4)
  265.         *t = '4';
  266.         else
  267.         *t = '8';
  268.         ++t;
  269.     }
  270.     *t = ')'; ++t;
  271.     break;
  272.     case ST_RelLabel:
  273.     if (s->st_Flags & SF_REGARGS) {
  274.         *t = '@';
  275.         ++t;
  276.     }
  277.  
  278.     *t = 'l'; ++t;
  279.     t = itodec(t, s->st_Label);
  280.  
  281.     if (s->st_Offset) {
  282.         if (s->st_Offset >= 0) {
  283.         *t = '+';
  284.         ++t;
  285.         }
  286.         t = itodec(t, s->st_Offset);
  287.     }
  288.     if (s->st_Flags & SF_CODE) {
  289.         if ((SmallCode || (s->st_Flags & SF_NEAR)) && !(s->st_Flags & SF_FAR)) {
  290.         *t = '('; ++t;
  291.         *t = 'p'; ++t;
  292.         *t = 'c'; ++t;
  293.         *t = ')'; ++t;
  294.         }
  295.     } else {
  296.         if ((SmallData || (s->st_Flags & SF_NEAR)) && !(s->st_Flags & SF_FAR)) {
  297.         if (SmallData == 2) {
  298.             *t = '.'; ++t;
  299.             *t = 'W'; ++t;
  300.         } else {
  301.             *t = '('; ++t;
  302.             *t = 'A'; ++t;
  303.             *t = '4'; ++t;
  304.             *t = ')'; ++t;
  305.         }
  306.         }
  307.     }
  308.     break;
  309.     case ST_RelName:
  310.     if (s->st_Flags & SF_REGARGS)
  311.         *t = '@';
  312.     else
  313.         *t = '_';
  314.     ++t;
  315.     movmem(s->st_Name->Name, t, s->st_Name->Len);
  316.     t += s->st_Name->Len;
  317.  
  318.     if (s->st_Offset) {
  319.         if (s->st_Offset >= 0) {
  320.         *t = '+';
  321.         ++t;
  322.         }
  323.         t = itodec(t, s->st_Offset);
  324.     }
  325.     if (s->st_Flags & SF_CODE) {
  326.         if ((SmallCode || (s->st_Flags & SF_NEAR)) && !(s->st_Flags & SF_FAR)) {
  327.         *t = '('; ++t;
  328.         *t = 'p'; ++t;
  329.         *t = 'c'; ++t;
  330.         *t = ')'; ++t;
  331.         }
  332.     } else {
  333.         if ((SmallData || (s->st_Flags & SF_NEAR)) && !(s->st_Flags & SF_FAR)) {
  334.         if (SmallData == 2) {
  335.             *t = '.'; ++t;
  336.             *t = 'W'; ++t;
  337.         } else {
  338.             *t = '('; ++t;
  339.             *t = 'A'; ++t;
  340.             *t = '4'; ++t;
  341.             *t = ')'; ++t;
  342.         }
  343.         }
  344.     }
  345.     break;
  346.     case ST_Push:
  347.     *t = '-'; ++t;
  348.     *t = '('; ++t;
  349.     *t = 's'; ++t;
  350.     *t = 'p'; ++t;
  351.     *t = ')'; ++t;
  352.     break;
  353.     default:
  354.     t += sprintf(t, "?%d", s->st_Type);
  355.     break;
  356.     }
  357.     *t = 0;
  358.     return(t);
  359. }
  360.  
  361. /*
  362.  *  Same physical storage, possibly different sizes
  363.  */
  364.  
  365. long
  366. SameStorage(s1, s2)
  367. Stor *s1, *s2;
  368. {
  369.     if ((s1->st_Flags ^ s2->st_Flags) & SF_LEA)
  370.     return(0);
  371.     if (s1->st_Type != s2->st_Type)
  372.     return(0);
  373.     if (s1->st_Type == ST_Reg)
  374.     return(s1->st_RegNo == s2->st_RegNo);
  375.  
  376.     switch(s1->st_Type) {
  377.     case ST_PtrConst:
  378.     return(s1->st_PtrConst == s2->st_PtrConst);
  379.     case ST_IntConst:
  380.     return(s1->st_IntConst == s2->st_IntConst);
  381.     case ST_FltConst:
  382.     return(s1->st_FltConst == s2->st_FltConst);
  383.     case ST_StrConst:
  384.     return(s1->st_StrConst == s2->st_StrConst);
  385.     case ST_RelArg:
  386.     return(s1->st_Offset == s2->st_Offset);
  387.     case ST_RelReg:
  388.     return(s1->st_RegNo == s2->st_RegNo && s1->st_Offset == s2->st_Offset);
  389.     case ST_RelLabel:
  390.     return(s1->st_Label == s2->st_Label && s1->st_Offset == s2->st_Offset);
  391.     case ST_RelName:
  392.     return(s1->st_Name == s2->st_Name && s1->st_Offset == s2->st_Offset);
  393.     case ST_RegIndex:
  394.     return(s1->st_RegNo == s2->st_RegNo && s1->st_Offset == s2->st_Offset && s1->st_RegNo2 == s2->st_RegNo2);
  395.     default:
  396.         dbprintf(("Bad storage type for same-compare %d\n", s1->st_Type));
  397.     }
  398.     Assert(0);
  399.     return(0); /* not reached */
  400. }
  401.  
  402. /*
  403.  *  Will the registers used in one storage structure interfere with the
  404.  *  registers used in another?
  405.  */
  406.  
  407. long
  408. SameRegister(s1, s2)
  409. Stor *s1, *s2;
  410. {
  411.     switch(s1->st_Type) {
  412.     case ST_Reg:
  413.     case ST_RelReg:
  414.     switch(s2->st_Type) {
  415.     case ST_Reg:
  416.     case ST_RelReg:
  417.         if (s1->st_RegNo == s2->st_RegNo)
  418.         return(1);
  419.         break;
  420.     case ST_RegIndex:
  421.         if (s1->st_RegNo == s2->st_RegNo || s1->st_RegNo == s2->st_RegNo2)
  422.         return(1);
  423.         break;
  424.     }
  425.     break;
  426.     case ST_RegIndex:
  427.     switch(s2->st_Type) {
  428.     case ST_Reg:
  429.     case ST_RelReg:
  430.         if (s2->st_RegNo == s1->st_RegNo || s2->st_RegNo == s1->st_RegNo2)
  431.         return(1);
  432.         break;
  433.     case ST_RegIndex:
  434.         if (s2->st_RegNo == s1->st_RegNo || s2->st_RegNo == s1->st_RegNo2 || s2->st_RegNo2 == s1->st_RegNo || s2->st_RegNo2 == s1->st_RegNo2)
  435.         return(1);
  436.         break;
  437.     }
  438.     break;
  439.     }
  440.     return(0);
  441. }
  442.  
  443. long
  444. RegisterMaskConflict(s1, mask)
  445. Stor *s1;
  446. ulong mask;
  447. {
  448.     switch(s1->st_Type) {
  449.     case ST_Reg:
  450.     case ST_RelReg:
  451.     if ((1 << s1->st_RegNo) & mask)
  452.         return(1);
  453.     break;
  454.     case ST_RegIndex:
  455.     if (((1 << s1->st_RegNo) | (1 << s1->st_RegNo2)) & mask)
  456.         return(1);
  457.     break;
  458.     case ST_RelName:
  459.     case ST_RelLabel:
  460.     if ((s1->st_Flags & (SF_FAR|SF_CODE)) == 0 && (mask & RF_A4))
  461.         return(1);
  462.     break;
  463.     case ST_RelArg:
  464.     if (mask & RF_A5)
  465.         return(1);
  466.     break;
  467.     }
  468.     return(0);
  469. }
  470.  
  471.  
  472. /*
  473.  *  Does the storage represent some sort of immediate value?  This includes
  474.  *  effective addresses
  475.  */
  476.  
  477. long
  478. ImmStorage(stor)
  479. Stor *stor;
  480. {
  481.     if (stor->st_Type == ST_IntConst || stor->st_Type == ST_PtrConst)
  482.     return(1);
  483.     if ((stor->st_Flags & SF_LEA) && (stor->st_Type == ST_RelLabel || stor->st_Type == ST_RelName))
  484.     return(1);
  485.     return(0);
  486. }
  487.  
  488. void
  489. outop(char *op, short siz, Stor *s, Stor *d)
  490. {
  491.     char *ptr = StorBuf[0];
  492.  
  493.     if (siz == 0)
  494.     siz = d->st_Size;
  495.     if (siz > 4)
  496.     siz = 5;
  497.  
  498.     *ptr = '\t'; ++ptr;
  499.     while ((*ptr = *op) != 0) {
  500.     ++ptr;
  501.     ++op;
  502.     }
  503.     if (siz >= 0) {
  504.     *ptr = '.'; ++ptr;
  505.     *ptr = SizC[siz]; ++ptr;
  506.     }
  507.     *ptr = '\t'; ++ptr;
  508.     if (s) {
  509.     ptr = StorToStringBuf(s, ptr);
  510.     *ptr = ','; ++ptr;
  511.     }
  512.     ptr = StorToStringBuf(d, ptr);
  513.     *ptr = '\n'; ++ptr;
  514.     fwrite(StorBuf[0], ptr - StorBuf[0], 1, stdout);
  515. }
  516.  
  517.  
  518. /*
  519.  *  Generate structured static/global data.
  520.  *
  521.  *  If the resident (-r) option is used we cannot generate data-data
  522.  *  relocations ... we must do them in an autoinit section using A4
  523.  *  relative addressing.
  524.  *
  525.  *  Most of the structural considerations are handled by GenBracedEq/Assign
  526.  *  which is forced for static/global initialization.
  527.  */
  528.  
  529. void
  530. GenStaticData(var)
  531. Var *var;
  532. {
  533.     if ((var->Flags & TF_ALIGNED) || var->Type->Align == 4)
  534.     printf("\tds.l\t0\n");
  535.     else if (var->Type->Align != 1)
  536.     printf("\tds.w\t0\n");
  537.  
  538.     if (var->var_Stor.st_Type == ST_RelName)
  539.     printf("_%s", SymToString(var->var_Stor.st_Name));
  540.     else
  541.     printf("l%ld", var->var_Stor.st_Label);
  542.  
  543.     if (var->u.AssExp == NULL) {
  544.     printf("\tds.b\t%ld\n", var->Type->Size);
  545.     } else {
  546.     /*
  547.      *  Generate the data from the expression.
  548.      */
  549.     puts("");
  550.     GenDataElm(var->u.AssExp, var->Type);
  551.     }
  552.     OutAlign = var->Type->Size & 3;
  553.  
  554.     /*
  555.      *    If a __config variable then generate an autoconfig section for
  556.      *    it.
  557.      */
  558.  
  559.     if (var->Flags & TF_CONFIG) {
  560.     printf("\tsection\tautoconfig,code\n");
  561.     printf("\tpea\t%s\n", StorToString(&var->var_Stor, NULL));
  562.     if (var->var_Stor.st_Size < 32768)
  563.         printf("\tpea\t%ld.W\n", var->var_Stor.st_Size);
  564.     else
  565.         printf("\tpea\t%ld\n", var->var_Stor.st_Size);
  566.     if (SmallCode || PIOpt)
  567.         printf("\tjsr\t__DiceConfig(pc)\n");
  568.     else
  569.         printf("\tjsr\t__DiceConfig\n");
  570.     AddAuxSub("DiceConfig");
  571.     puts(LastSectBuf);
  572.     }
  573. }
  574.  
  575. /*
  576.  *  GegnDataElm()
  577.  *
  578.  *  run through element generation for expression, which MUST be of type
  579.  *  TokExpAssBlock
  580.  */
  581.  
  582. void
  583. GenDataElm(exp, type)
  584. Exp *exp;
  585. Type *type;
  586. {
  587.     short savePass = GenPass;
  588.  
  589.     Assert(exp->ex_Token == TokExpAssBlock);
  590.     Assert(exp->ex_Type == type);
  591.  
  592.     /*
  593.      *    Run through expression generation passes
  594.      */
  595.  
  596.     GenGlobal = 1;
  597.     GenPass = 0;
  598.     (*exp->ex_Func)(&exp);
  599.     GenPass = 1;
  600.     AutoAggregateBeg(NULL, exp->ex_Type);
  601.     (*exp->ex_Func)(&exp);
  602.     AutoAggregateEnd();
  603.     GenPass = savePass;
  604.     GenGlobal = 0;
  605. }
  606.  
  607.  
  608. char *
  609. itohex(ptr, val)
  610. char *ptr;
  611. ulong val;
  612. {
  613.     static char HA[] = { "0123456789ABCDEF" };
  614.     short dig = 8;
  615.     char *p;
  616.  
  617.     if (val < 0x10000) {
  618.     dig = 4;
  619.     if (val < 0x100)
  620.         dig = 2;
  621.     }
  622.     ptr += dig;
  623.     p = ptr;
  624.     *p-- = 0;
  625.     while (dig--) {
  626.     *p-- = HA[(short)val & 0xF];
  627.     val >>= 4;
  628.     }
  629.     return(ptr);
  630. }
  631.  
  632. char *
  633. itodec(ptr, val)
  634. char *ptr;
  635. ulong val;
  636. {
  637.     if ((long)val < 0) {
  638.     val = -val;
  639.     *ptr++ = '-';
  640.     }
  641.     if (val < 10) {
  642.     *ptr++ = '0' + val;
  643.     } else if (val < 100) {
  644.     *ptr++ = '0' + val / 10;
  645.     *ptr++ = '0' + val % 10;
  646.     } else {
  647.     char buf[16];
  648.     short i = 15;
  649.  
  650.     while (val > 32767) {
  651.         buf[i--] = '0' + val % 10;
  652.         val /= 10;
  653.     }
  654.     while (val) {
  655.         buf[i--] = '0' + (uword)val % (uword)10;
  656.         val = (short)val / (short)10;
  657.     }
  658.     while (i != 15)
  659.         *ptr++ = buf[++i];
  660.     }
  661.     *ptr = 0;
  662.     return(ptr);
  663. }
  664.  
  665. static long AGLabel;
  666. static long AGIndex;
  667. static TmpAggregate *AGBase;
  668. static TmpAggregate **AGNext;
  669.  
  670. void
  671. AutoAggregateBeg(s, type)
  672. Stor *s;
  673. Type *type;
  674. {
  675.     AGLabel = AllocLabel();
  676.     AGBase = NULL;
  677.     AGNext = &AGBase;
  678.  
  679.     if (GenGlobal == 0) {
  680.     setmem(s, sizeof(Stor), 0);
  681.     s->st_Type = ST_RelLabel;
  682.     s->st_Offset = 0;
  683.     s->st_Size = type->Size;
  684.     s->st_Label = AGLabel;
  685.     s->st_Flags = (SmallData) ? SF_NEAR : SF_FAR;
  686.     }
  687. }
  688.  
  689. void
  690. AutoAggregate(ptr, n)
  691. void *ptr;
  692. long n;
  693. {
  694.     TmpAggregate *ag = *AGNext;
  695.  
  696.     if (ag == NULL || ag->ta_Bytes - ag->ta_Index < n) {
  697.     long v = (n > 512) ? n : 512;
  698.  
  699.     if (ag)
  700.         AGNext = &ag->ta_Next;
  701.  
  702.     ag = malloc(sizeof(TmpAggregate) + v);
  703.  
  704.     if (ag == NULL)
  705.         NoMem();
  706.     ag->ta_Next = NULL;
  707.     ag->ta_Buf = (char *)(ag + 1);
  708.     ag->ta_Index = 0;
  709.     ag->ta_Bytes = v;
  710.     *AGNext = ag;
  711.     }
  712.     {
  713.     char *dptr = ag->ta_Buf + ag->ta_Index;
  714.  
  715.     if (ptr)
  716.         movmem(ptr, dptr, n);
  717.     else
  718.         setmem(dptr, n, 0);
  719.     }
  720.     ag->ta_Index += n;
  721. }
  722.  
  723. void
  724. AutoAggregateSync()
  725. {
  726.     TmpAggregate *ag, *agNext;
  727.  
  728.     if (GenGlobal == 0 && AGLabel) {
  729.     asm_segment(&DummyDataVar);
  730.     printf("\tds.l\t0\n");
  731.     printf("l%ld\n", AGLabel);
  732.     AGLabel = 0;
  733.     }
  734.     for (ag = AGBase; ag; ag = agNext) {
  735.     long i;
  736.     short col = 0;
  737.  
  738.     agNext = ag->ta_Next;
  739.  
  740.     if ((AGIndex & 3) == 0 && (ag->ta_Index & 3) == 0) {
  741.         for (i = 0; i < ag->ta_Index; i += 4) {
  742.         if (col == 0) {
  743.             printf("\n\tdc.l\t");
  744.         } else {
  745.             putc(',', stdout);
  746.             ++col;
  747.         }
  748.         col += printf("$%lx", ToMsbOrder(*(unsigned long *)(ag->ta_Buf + i)));
  749.         if (col > 120)
  750.             col = 0;
  751.         }
  752.     } else if ((AGIndex & 1) == 0 && (ag->ta_Index & 1) == 0) {
  753.         for (i = 0; i < ag->ta_Index; i += 2) {
  754.         if (col == 0) {
  755.             printf("\n\tdc.w\t");
  756.         } else {
  757.             putc(',', stdout);
  758.             ++col;
  759.         }
  760.         col += printf("$%lx", ToMsbOrderShort(*(unsigned short *)(ag->ta_Buf + i)));
  761.         if (col > 120)
  762.             col = 0;
  763.         }
  764.     } else {
  765.         for (i = 0; i < ag->ta_Index; i += 1) {
  766.         if (col == 0) {
  767.             printf("\n\tdc.b\t");
  768.         } else {
  769.             putc(',', stdout);
  770.             ++col;
  771.         }
  772.         col += printf("$%lx", (unsigned long)*(unsigned char *)(ag->ta_Buf + i));
  773.         if (col > 120)
  774.             col = 0;
  775.         }
  776.     }
  777.     AGIndex += ag->ta_Index;
  778.     puts("");
  779.     free(ag);
  780.     }
  781.     AGBase = NULL;
  782.     AGNext = &AGBase;
  783. }
  784.  
  785. void
  786. AutoAggregateEnd()
  787. {
  788.     if (GenGlobal == 0 && AGLabel) {
  789.     asm_segment(&DummyDataVar);
  790.     printf("\tds.l\t0\n");
  791.     printf("l%ld\n", AGLabel);
  792.     AGLabel = 0;
  793.     }
  794.     AutoAggregateSync();
  795.     puts("");
  796.     if (GenGlobal == 0) {
  797.     asm_segment(&DummyCodeVar);
  798.     }
  799. }
  800.  
  801.